package com.duobaoyu.dby.supply.db.repository.message.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.supply.core.common.util.DeflaterUtils;
import com.duobaoyu.dby.supply.db.entity.message.DelayMessage;
import com.duobaoyu.dby.supply.db.repository.message.DelayMessageRepository;
import com.duobaoyu.dby.supply.db.util.OperateAuthUtil;
import com.mongodb.client.result.UpdateResult;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName DelayMessageServiceImpl
 * @createTime 11:28:00 2023/10/07
 */
@Repository
@RequiredArgsConstructor
public class DelayMessageRepositoryImpl /*extends DbyServiceImpl<DelayMessageMapper, DelayMessage>*/ implements DelayMessageRepository {

    private final MongoTemplate mongoTemplate;

    @Override
    public boolean save(DelayMessage delayMessage) {
        delayMessage.setCreateTime(LocalDateTime.now());
        delayMessage.setUpdateTime(LocalDateTime.now());
        delayMessage.setUpdateBy(OperateAuthUtil.getAdministrator());
        delayMessage.setCreateBy(OperateAuthUtil.getAdministrator());
        delayMessage.setDelFlag(CommonConstants.ZERO);
        delayMessage.setRetryCount(CommonConstants.ZERO);
        delayMessage.setVersion(CommonConstants.ZERO);
        if (StringUtils.isNotBlank(delayMessage.getMessage())) {
            delayMessage.setMessage(DeflaterUtils.zipString(delayMessage.getMessage()));
        }
        DelayMessage save = mongoTemplate.save(delayMessage);
        return Optional.ofNullable(save).map(DelayMessage::getId).map(StringUtils::isNotBlank).orElse(false);
    }

    @Override
    public boolean updateStatusById(String delayMessageId, Integer messageStatus, Integer preStatus,boolean incrementalRetryCount) {
        Query query = new Query(Criteria.where("_id").is(delayMessageId));
        if (Objects.nonNull(preStatus)) {
            query.addCriteria(Criteria.where("status").is(preStatus));
        }
        Update update = new Update();
        if(incrementalRetryCount) {
            update.inc("retry_count", CommonConstants.ONE);
        }
        update.inc("version", CommonConstants.ONE);
        update.set("update_time", LocalDateTime.now());
        update.set("update_by", OperateAuthUtil.getAdministrator());
        update.set("status", messageStatus);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, DelayMessage.class);
        return updateResult.wasAcknowledged();
    }

    @Override
    public boolean updateStatusById(String delayMessageId, Integer messageStatus,boolean incrementalRetryCount) {
        return this.updateStatusById(delayMessageId, messageStatus, null,incrementalRetryCount);
    }

    @Override
    public DelayMessage findByUniqueKey(String uniqueKey) {
        Criteria criteria = new Criteria();
        criteria.and("del_flag").is(CommonConstants.ZERO);
        criteria.and("unique_key").is(uniqueKey);
        Query query = new Query(criteria);
        DelayMessage delayMessage = mongoTemplate.findOne(query, DelayMessage.class);
        if (Objects.nonNull(delayMessage) && StringUtils.isNotBlank(delayMessage.getMessage())) {
            delayMessage.setMessage(DeflaterUtils.unzipString(delayMessage.getMessage()));
        }
        return delayMessage;
    }

    @Override
    public boolean existsByUniqueKey(String uniqueKey) {
        Criteria criteria = new Criteria();
        criteria.and("del_flag").is(CommonConstants.ZERO);
        criteria.and("unique_key").is(uniqueKey);
        Query query = new Query(criteria);
        return mongoTemplate.exists(query, DelayMessage.class);
    }

    @Override
    public Page<DelayMessage> page(Page<Object> pageParam, Query query) {
        // 12. 总记录数
        long total = mongoTemplate.count(query, DelayMessage.class);
        // 8. 查询返回指定字段 (自定义列表)
        //query.fields().include()
        // 10. 分页、排序
        int pageNo = Long.valueOf(pageParam.getCurrent() - 1).intValue();
        int size = Long.valueOf(pageParam.getSize()).intValue();
        query.with(PageRequest.of(pageNo, size, Sort.by(Sort.Order.desc("create_time"))));
        List<DelayMessage> delayMessages = mongoTemplate.find(query, DelayMessage.class);
        if (CollectionUtils.isNotEmpty(delayMessages)) {
            for (DelayMessage record : delayMessages) {
                if (StringUtils.isNotBlank(record.getMessage())) {
                    record.setMessage(DeflaterUtils.unzipString(record.getMessage()));
                }
            }
        }
        Page<DelayMessage> page = Page.of(pageNo, size, total);
        page.setRecords(delayMessages);
        return page;
    }

    @Override
    public Boolean updateDelayMessageStatus(Query query, Update update) {
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, DelayMessage.class);
        return updateResult.wasAcknowledged();
    }

    @Override
    public DelayMessage findById(String delayMessageId) {
        DelayMessage delayMessage = mongoTemplate.findById(delayMessageId, DelayMessage.class);
        if (Objects.nonNull(delayMessage) && StringUtils.isNotBlank(delayMessage.getMessage())) {
            delayMessage.setMessage(DeflaterUtils.unzipString(delayMessage.getMessage()));
        }
        return delayMessage;
    }

    @Override
    public List<DelayMessage> delayMessageList(int skipCount, int limit, List<Integer> messageStatusList, Long currentMilli, Integer lteRetryCount) {
        Criteria criteria = new Criteria();
        if(CollectionUtils.isNotEmpty(messageStatusList)) {
            criteria.and("status").in(messageStatusList);
        }
        if(Objects.nonNull(currentMilli)) {
            criteria.and("delay_time").lte(currentMilli);
        }
        if(Objects.nonNull(lteRetryCount)) {
            criteria.and("retry_count").lte(lteRetryCount);
        }
        criteria.and("del_flag").is(CommonConstants.ZERO);
        List<DelayMessage> delayMessages = mongoTemplate.find(Query.query(criteria).skip(skipCount).limit(limit), DelayMessage.class);
        if (CollectionUtils.isNotEmpty(delayMessages)) {
            for (DelayMessage record : delayMessages) {
                if (StringUtils.isNotBlank(record.getMessage())) {
                    record.setMessage(DeflaterUtils.unzipString(record.getMessage()));
                }
            }
        }
        return delayMessages;
    }
}
